
//altera message_off 10036

`include "alt_mem_ddrx_define.iv"

`timescale 1 ps / 1 ps
module alt_mem_ddrx_odt_gen
    #( parameter
        CFG_DWIDTH_RATIO                = 2,
        CFG_ODT_ENABLED                 = 1,
        CFG_MEM_IF_CHIP                 = 1, //one_hot
        CFG_MEM_IF_ODT_WIDTH            = 1,
        CFG_PORT_WIDTH_OUTPUT_REGD      = 1,
        CFG_PORT_WIDTH_CAS_WR_LAT       = 4,
        CFG_PORT_WIDTH_TCL              = 4,
        CFG_PORT_WIDTH_ADD_LAT          = 3,
        CFG_PORT_WIDTH_TYPE             = 3,
        CFG_PORT_WIDTH_WRITE_ODT_CHIP   = 1,
        CFG_PORT_WIDTH_READ_ODT_CHIP    = 1
    )
    (
        ctl_clk,
        ctl_reset_n,
        
        //Configuration Interface
        cfg_type,
        cfg_tcl,
        cfg_add_lat,
        cfg_write_odt_chip,
        cfg_read_odt_chip,
        cfg_burst_length,
        
        //Arbiter Interface
        bg_do_read,
        bg_do_write,
        bg_to_chip, //one_hot
        
        //AFI Interface
        afi_odt
    );
    
    //=================================================================================================//
    //        input/output declaration                                                                 //
    //=================================================================================================//
    
    input                                                     ctl_clk;
    input                                                     ctl_reset_n;
    
    //Input from Configuration Interface
    
    input   [CFG_PORT_WIDTH_TYPE                -1:0]         cfg_type;
    input   [CFG_PORT_WIDTH_TCL                 -1:0]         cfg_tcl;
    input   [CFG_PORT_WIDTH_ADD_LAT             -1:0]         cfg_add_lat;
    input                                                     cfg_write_odt_chip;
    input                                                     cfg_read_odt_chip;
    input   [4:0]                                             cfg_burst_length;
     
    //Inputs from Arbiter Interface
    
    input                                                     bg_do_read;
    input                                                     bg_do_write;
    input                                                     bg_to_chip;
    
    //Output to AFI Interface
    
    output  afi_odt;
    
    //=================================================================================================//
    //        reg/wire declaration                                                                     //
    //=================================================================================================//
    
    wire                     write_odt_chip;
    wire                     read_odt_chip ;
    
    wire                     ddr2_odt_l;
    wire                     ddr2_odt_h;
    reg                      int_odt_l;
    reg                      int_odt_h;
    reg                      int_odt_i_1;
    reg                      int_odt_i_2;
    reg                      int_write_odt_chip;
    reg                      int_read_odt_chip;
    
    integer i;
    
    //=================================================================================================//
    //        cfg_write_odt_chip & cfg_read_odt_chip definition                                        //
    //=================================================================================================//
    
    
    /*
    DDR2
    four or more chip selects odt scheme, assumes two ranks per dimm
    .---------------------------------------++---------------------------------------.
    |             write/read to             ||                odt to                 |
    +---------+---------+---------+---------++---------+---------+---------+---------+
    | chipJ+0 | chipJ+1 | chipJ+2 | chipJ+3 || chipJ+0 | chipJ+1 | chipJ+2 | chipJ+3 |
    |=--------+---------+---------+---------++---------+---------+---------+--------=|
    |    1    |         |         |         ||         |         |    1    |         |
    +---------+---------+---------+---------++---------+---------+---------+---------+
    |         |    1    |         |         ||         |         |         |    1    |
    +---------+---------+---------+---------++---------+---------+---------+---------+
    |         |         |    1    |         ||    1    |         |         |         |
    +---------+---------+---------+---------++---------+---------+---------+---------+
    |         |         |         |    1    ||         |    1    |         |         |
    '---------+---------+---------+---------++---------+---------+---------+---------'
    */
    
    //Unpack read/write_odt_chip array into per chip array

    assign write_odt_chip = cfg_write_odt_chip;
    assign read_odt_chip  = cfg_read_odt_chip ;

    always @(*)
    begin
        int_write_odt_chip = 0;
        int_read_odt_chip = 0;
        if (bg_to_chip)
        begin
            int_write_odt_chip = write_odt_chip;
            int_read_odt_chip = read_odt_chip;
        end
    end
    
    //=================================================================================================//
    //        Instantiate DDR2 ODT generation Block                                                    //
    //=================================================================================================//

    alt_mem_ddrx_ddr2_odt_gen
    # (
        .CFG_DWIDTH_RATIO           (CFG_DWIDTH_RATIO),
        .CFG_PORT_WIDTH_ADD_LAT     (CFG_PORT_WIDTH_ADD_LAT),
        .CFG_PORT_WIDTH_OUTPUT_REGD (CFG_PORT_WIDTH_OUTPUT_REGD),
        .CFG_PORT_WIDTH_TCL         (CFG_PORT_WIDTH_TCL)
    )
    alt_mem_ddrx_ddr2_odt_gen_inst
    (
        .ctl_clk                    (ctl_clk),
        .ctl_reset_n                (ctl_reset_n),
        .cfg_tcl                    (cfg_tcl),
        .cfg_add_lat                (cfg_add_lat),
        .cfg_burst_length           (cfg_burst_length),
        .bg_do_write                (bg_do_write & int_write_odt_chip),
        .bg_do_read                 (bg_do_read & int_read_odt_chip),
        .int_odt_l                  (ddr2_odt_l),
        .int_odt_h                  (ddr2_odt_h)
    );

    //=================================================================================================//
    //        Instantiate DDR3 ODT generation Block                                                    //
    //=================================================================================================//
    
    //=================================================================================================//
    //        ODT Output generation based on memory type and ODT feature turned ON or not              //
    //=================================================================================================//
    
    assign afi_odt = ddr2_odt_l;

endmodule
